//------------------------------------------------------------------------------
//  <copyright file="KukaLBR4PlusController.h" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//  </copyright>
//------------------------------------------------------------------------------	

#pragma once

#include "ClientMessages.h"
#include "ControllerClientMessageHandler.h"
#include "ControllerThreadParameters.h"
#include "IFRIConnection.h"
#include "KukaLBR4PlusControllerExports.h"
#include "SharedBufferParameters.h"
#include "KukaLBR4ControllerCommon.h"

#include "ControllerStateMachineExports.h"
#include <ControllerStateMachineDescription.cs>
#include <ControllerExecutionEngine.h>
#include <KukaLBR4Definitions.h>
#include <Windows.h>

#define MS_PER_SEC 1000.0

using namespace KukaLBR4ControllerCommonNS;

/// <remarks>
/// This class is responsible for managing the coordination between a controller state machine
/// configured to control a KUKA LBR 4+ manipulator that is connected as an FRI client
/// and an upstream client that wants to execute controllers and get feedback from the manipulator.
/// The primary functions are to start a thread that will configure and execute a controller state
/// machine for the LBR manipulator and execute control commands (per the controller state machine)
/// and get feedback via a Fast Research Interface (FRI) connection to the LBR.  When the control
/// thread is started, a <c>ControllerClientMessageHandler</c> object is returned to the creator
/// that is used to exchange data/commands between the upstream client and the controller thread.

/// <summary> Main function for controller thread. </summary>
DWORD WINAPI KukaLBR4ControllerThreadFunction(LPVOID pParam);

/// <summary>
/// Manages creation of and communication with a thread executing a controller state
/// machine for a Kuka LBR.
/// </summary>
class KUKALBR4PLUSCONTROLLER_DLLEXPORTIMPORT KukaLBR4PlusController
{
public:
	/// <summary> Initializes a new instance of the <c>KukaLBR4PlusController</c> class </summary>
	KukaLBR4PlusController();

	/// <summary> dtor </summary>
	~KukaLBR4PlusController();

	/// <summary> Initialize buffers and start the IO and Controller threads </summary>
	/// <param name=clientConnection> Object used to communicate with upstream client </param>
	/// <param name=friConnection> Object implementing FRI server. </param>
	/// <param name=lockOnProcessMessage>
	/// If true, will use a <c>ControllerClientMessageHandler</c> that locks on
	/// calls to ProcessMessage, making this function safe to call from multiple threads.
	/// This can be used when more than one thread needs to independently sample the feedback from the controller.
	/// For example to attach a visualzation client that runs on a different
	/// thread than the control routine (which might be a unit test etc...), and independently
	/// polls the controller for feedback.
	/// </param>
	ControllerClientMessageHandler *StartKukaLBR4PlusController(IFRIConnection *pFriConnection, bool lockOnProcessMessage = false);

	/// <summary> Blocks until the controller thread exits. </summary>
	/// <param name="timeOutInMs">
	/// A time out value after which to terminate the controller thread.
	/// In a timeout condition, thread shutdown is not graceful, and timeout
	/// values other than 0 should only be given when performing SW only tests.
	/// </param>
	/// <returns> The result of <c>WaitForSingleObject</c> on the controller thread. </returns>
	DWORD KukaLBR4PlusController::WaitForControllerExit(DWORD timeOutInMs);

	/// <summary> Somewhat arbitrary point to wrap around sequence numbers for KRL commands. </summary>
	static const int MaxKrlMotionCommandSequenceNumber = 10000;

private:
	/// <summary> Number of threads to be started. </summary>
	static const unsigned int ThreadCount = 1;

	/// <summary> Thread number of the controller thread. </summary>
	static const unsigned int ControllerThread = 0;

	/// <summary> Arry with IDs of threads. </summary>
	DWORD dwThreadIdArray[ThreadCount];

	/// <summary> Array of handles to threads. </summary>
	HANDLE hThreadArray[ThreadCount];

	/// <summary> Manages communcation between upstream client and controller thread. </summary>
	ControllerClientMessageHandler *pClientMessageHandler;

	/// <summary>
	/// Parameters related to shared buffers geiven used by controller thread and
	/// <c>ControllerClientMessageHandler</c> to exchange data.
	/// </summary>
	SharedBufferParameters *pSharedBufferParameters;

	/// <summary> 
	/// Contains the <c>SharedBufferParameters</c> and <c>IFRIConnection</c> information
	/// for initializing the controller thread.
	/// </summary>
	ControllerThreadParameters *pControllerThreadParameters;
};
